import matplotlib.pyplot as plt
import numpy as np
import argparse
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.ticker import FormatStrFormatter
import oss2  
import io
import datetime
from scipy.optimize import curve_fit  
# 创建 OSS 客户端实例  
auth = oss2.Auth('LTAI5tGPkHofe2wfSkE23csC', 'Tvw6H18pOrlaOzXYI0OcMu87XzbFwT')  
bucket = oss2.Bucket(auth, 'oss-cn-hangzhou.aliyuncs.com', 'nanchangmo')  
object_name = 'lvbang_area/out_20231013_000001.csv'
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.rcParams['axes.unicode_minus'] = False

parser = argparse.ArgumentParser()   
parser.add_argument("--rate", default=1.0, help="铝棒镂空的比例")  
parser.add_argument("--length", default=6000, help="铝棒长度")  
parser.add_argument("--loc", default=(-1000, 4000), help="铝棒堆所在位置的范围")
parser.add_argument("--grid_len", default=20, help="计算铝棒侧面积的窗口大小")
parser.add_argument("--file", default='C:/Users/赵浩中/PycharmProjects/pythonProject1/data/lvbang/6035-B3/out_20231013_000001.csv', help="读取文件路径") 
args = parser.parse_args()

# def get_now_datetime():
#     now = datetime.datetime.now()
#     return str(now.strftime("%Y-%m-%d-%H-%M-%S"))
# @app.route('/area_2d/')
def area_2d(object_name, camera_id, loc, grid_len, length, rate, angle=1, h=-3950):
    auth = oss2.Auth('LTAI5tGPkHofe2wfSkE23csC', 'Tvw6H18pOrlaOzXYI0OcMu87XzbFwT')  
    bucket = oss2.Bucket(auth, 'oss-cn-hangzhou.aliyuncs.com', 'nanchangmo') 
    content = bucket.get_object(object_name)
    data = content.read()
    file = io.BytesIO(data)
    data = np.loadtxt(file, delimiter=',')
    # 最大全景出图
    xmin = -10000
    xmax = 10000
    ymin = -10000
    ymax = 10000

    # 获取角度、距离和激光强度数据列
    angles = data[:, 2]
    distances = data[:, 1]

    pi = 3.141592653
    # x = distances * np.sin(angles / 180 * pi)*np.cos(45 / 180 * pi)
    x = distances * np.sin(angles / 180 * pi)
    y = distances * np.cos(angles / 180 * pi)

    # 旋转校准
    theta = angle
    x = x * np.cos(theta / 180 * pi) - y * np.sin(theta / 180 * pi)
    y = x * np.sin(theta / 180 * pi) + y * np.cos(theta / 180 * pi)

    condition_all = (x > xmin) & (x < xmax) & (y > ymin) & (y < ymax)
    x_all = x[condition_all]
    y_all = y[condition_all]

    condition = (x > loc[0]) & (x < loc[1]) & (y > ymin) & (y < ymax)
    x = x[condition]
    y = y[condition]
    x -= x_all.min()
    y -= h

    x_all -= x_all.min()
    y_all -= h

    area = 0
    height = []
    dict = {}

    for i in range(0, 4001, grid_len):
        for j in range(len(x)):
            if x[j] >= i and x[j] < i + grid_len:
                if i not in dict:
                    dict[i] = [j]
                else:
                    dict[i].append(j)

    for key in dict:
        h = 0
        for i in dict[key]:
            h += y[i]
        height.append(h / len(dict[key]))

    for i in height:
        area += 20 * i
    volume = area / 1e6 * length / 1000 * rate
    area /= 1e6

    fig = plt.figure(figsize=(100, 100))
    ax1 = fig.add_subplot(111)
    scatter = ax1.scatter(x_all, y_all, s=0.05, c='blue')
    # scatter = ax1.scatter(x, y, s=0.05)
    ax1.set_title("二维展示")
    ax1.set_xlabel('x轴(毫米)')
    ax1.set_ylabel('y轴(毫米)')

    # 设置横轴刻度位置和标签
    x_ticks = np.arange(0, max(x_all)+500, 1000)
    ax1.set_xticks(x_ticks)
    ax1.set_xticklabels(x_ticks)
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%d'))

    # 设置纵轴刻度位置和标签
    y_ticks = np.arange(0, max(y_all)+500, 1000)
    ax1.set_yticks(y_ticks)
    ax1.set_yticklabels(y_ticks)
    ax1.yaxis.set_major_formatter(FormatStrFormatter('%d'))
    x = []
    for i in dict.keys():
        x.append(int(i)+10)
    ax1.bar(x, height, width=20, alpha=0.5)
    ax1.set_aspect(1.5) 
    plt.title('The area is %.5f' % area)
    plt.show()
    buffer = io.BytesIO()
    fig.savefig(buffer, format='png')
    buffer.seek(0)
    # return area
    bucket.put_object('lvbang_area/%s/%s.png' % (camera_id, datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")), buffer.getvalue())
    plt.close()

def area(data, loc, grid_len, length, rate, angle=1, h=-3950):

    # 最大全景出图
    xmin = -10000
    xmax = 10000
    ymin = -10000
    ymax = 10000

    # 获取角度、距离和激光强度数据列
    angles = data[:, 2]
    distances = data[:, 1]

    pi = 3.141592653
    # x = distances * np.sin(angles / 180 * pi)*np.cos(45 / 180 * pi)
    x = distances * np.sin(angles / 180 * pi)
    y = distances * np.cos(angles / 180 * pi)

    # 旋转校准
    theta = angle
    x = x * np.cos(theta / 180 * pi) - y * np.sin(theta / 180 * pi)
    y = x * np.sin(theta / 180 * pi) + y * np.cos(theta / 180 * pi)

    condition_all = (x > xmin) & (x < xmax) & (y > ymin) & (y < -500)
    x_all = x[condition_all]
    y_all = y[condition_all]

    condition = (x > loc[0]) & (x < loc[1]) & (y > ymin) & (y < -500)

    x = x[condition]
    y = y[condition]
    x -= x_all.min()
    y -= h

    x_all -= x_all.min()
    y_all -= h

    condition_wall = (x_all > 300) & (x_all < 450) & (y_all > y.min()) & (y_all < 2500)
    x_wall = x_all[condition_wall]
    y_wall = y_all[condition_wall] 

    area = 0
    height = []
    dict = {}

    # 划分格，找到每个格子中点对应y的索引
    for i in range(550, 3261, grid_len):
        for j in range(len(x)):
            if x[j] >= i and x[j] < i + grid_len:
                if i not in dict:
                    dict[i] = [j]
                else:
                    dict[i].append(j)

    for key in list(dict.keys()):
        if key + grid_len in dict.keys():
            left = key
            break
        else:
            del dict[key]

    # 拟合墙壁那段直线
    def func(x, a, b):  
        return a * x + b

    popt, pcov = curve_fit(func, x_wall, y_wall)  
    a, b = popt  
    # x_a = np.arange(300, min(dict.keys()), 20)   #  需要填补的x区间
    gap = 0
    start = left - gap if gap else 300
    x_a = np.arange(start, left, 20)   #  需要填补的x区间
    y_a = a * x_a + b
    y_a = np.where(y_a < 0, 0, y_a)  #  拟合出直线点的y坐标
    # exit()

    # x_fill = [y[max(dict[min(dict.keys())])]] * len(y_a)
    x_fill = [y[min(dict[left])]] * len(y_a)
    x_fill = x_fill - y_a  # 填充的高度
    x_fill = np.where(x_fill < 0, 0, x_fill)

    for key in dict:
        h = 0
        for i in dict[key]:
            h = max(h, y[i])
        height.append(h)

    for i in height:
        area += 20 * i
    for i in x_fill:
        area += i * 20
    volume = area / 1e6 * length / 1000 * rate
    area /= 1e6

    # x_fill = np.append(x_fill, height)
    # y_a = np.append(y_a, list(dict.keys()))
    # print(len(y_a), len(x_fill))
    # # print(y_a)
    # fig = plt.figure(figsize=(100, 100))
    # plt.bar(y_a, x_fill, width=20, alpha=0.5, color='c')
    # plt.show()

    fig = plt.figure(figsize=(100, 100))
    ax1 = fig.add_subplot(111)
    scatter = ax1.scatter(x_all, y_all, s=0.05, c='blue')
    # scatter = ax1.scatter(x, y, s=0.05)
    ax1.set_title("二维展示")
    ax1.set_xlabel('x轴(毫米)')
    ax1.set_ylabel('y轴(毫米)')

    # 设置横轴刻度位置和标签
    x_ticks = np.arange(0, max(x_all)+500, 1000)
    ax1.set_xticks(x_ticks)
    ax1.set_xticklabels(x_ticks)
    ax1.xaxis.set_major_formatter(FormatStrFormatter('%d'))

    # 设置纵轴刻度位置和标签
    y_ticks = np.arange(0, max(y_all)+500, 1000)
    ax1.set_yticks(y_ticks)
    ax1.set_yticklabels(y_ticks)
    ax1.yaxis.set_major_formatter(FormatStrFormatter('%d'))
    x = []
    for i in dict.keys():
        x.append(int(i)+10)
    plt.bar(x, height, width=20, alpha=0.5, color='c')
    plt.bar(x_a, x_fill, width=20, bottom=y_a, alpha=0.5, color='c')
    # plt.plot(x_a, y_a)
    ax1.set_aspect('equal') 
    plt.title('The area is %.5f' % area)
    # plt.savefig('C:/Users/赵浩中/PycharmProjects/pythonProject1/data/lvbang/新建文件夹/6035.png')
    plt.show()
    plt.close()

# 进行校准 loc为选定校准的地面区域
def adjust(data, loc=(2500, 5500, -4500, -3500)):
    angles = data[:, 2]
    distances = data[:, 1]

    pi = 3.141592653
    x = distances * np.sin(angles / 180 * pi)
    y = distances * np.cos(angles / 180 * pi)

    condition = (x > loc[0]) & (x < loc[1]) & (y > loc[2]) & (y < loc[3])
    x = x[condition]
    y = y[condition]

    min_std = 999999
    angle = 0
    for theta in range(-10, 11):
        x1 = x * np.cos(theta / 180 * pi) - y * np.sin(theta / 180 * pi)
        y1 = x * np.sin(theta / 180 * pi) + y * np.cos(theta / 180 * pi)
        std_theta = np.std(y1) 
        if std_theta < min_std:
            min_std = std_theta
            angle = theta
            height = y1.mean()
    return angle, height

if __name__ == '__main__':
    # content = bucket.get_object(object_name)
    # data = content.read()
    # file = io.BytesIO(data)
    # data = np.loadtxt(file, delimiter=',') 
    # data = np.loadtxt(args.file, delimiter=',')
    # angle, height = adjust(data)
    # print(angle, height)

    # area_2d(object_name, 11, args.loc, args.grid_len, args.length, args.rate)

    # 6033  3 -4004.555126217022
    # 6034  3 -4067.8378533644404
    # 6035  1 -3964.138223847988

    data = np.loadtxt('C:/Users/赵浩中/PycharmProjects/pythonProject1/data/lvbang/新建文件夹/6035__.csv', delimiter=',')
    angle, height = adjust(data, loc=(2500, 5000, -4500, -3500))
    print(angle, height)
    area(data, loc=args.loc, grid_len=args.grid_len, length=args.length, rate=args.rate, angle=angle, h=height)